package bg.code.commons.plugin.ui.model;

import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 郑兴泉 956607644@qq.com
 * @data 2020/3/20
 * 描述：
 */
public class MethodTableModel extends AbstractTableModel {

    private final List<MethodParamTable> methodParamTables;
    private final Object[][] columns;
    private static final IEditTableCellCallback EDIT_TABLE_CELL_CALLBACK = new EditTableCellCallback();
    private static final IEditTableCellCallback EMPTY_EDIT_TABLE_CELL_CALLBACK = new EmptyEditTableCellCallback();
    private static final List<TableHeader> TABLE_HEADERS = new ArrayList<>(10);

    static {
        TABLE_HEADERS.add(new TableHeader("序号", false, EMPTY_EDIT_TABLE_CELL_CALLBACK));
        TABLE_HEADERS.add(new TableHeader("*", false, EMPTY_EDIT_TABLE_CELL_CALLBACK));
        TABLE_HEADERS.add(new TableHeader("是否生成(可编辑)", true, (headers, columns, rowIndex, cellIndex) -> {
            return cellIndex == 2;
        }));
        TABLE_HEADERS.add(new TableHeader("方法名称(可编辑)", true, EDIT_TABLE_CELL_CALLBACK));
        TABLE_HEADERS.add(new TableHeader("请求路径名称(可编辑)", true, EDIT_TABLE_CELL_CALLBACK));
        TABLE_HEADERS.add(new TableHeader("完整请求路径名称", false, EMPTY_EDIT_TABLE_CELL_CALLBACK));
        TABLE_HEADERS.add(new TableHeader("权限标识名称", false, EMPTY_EDIT_TABLE_CELL_CALLBACK));
    }

    public MethodTableModel(List<MethodParamTable> javaFields) {
        this.methodParamTables = javaFields;
        this.columns = new Object[javaFields.size()][TABLE_HEADERS.size()];
        int index = 0;
        for (MethodParamTable vo : methodParamTables) {
            columns[index] = new Object[]{
                    index + 1,
                    vo.getCellName(),
                    vo.isGenState(),
                    vo.getMethodName(),
                    vo.getRequestName(),
                    vo.getAllRequestName(),
                    vo.getPermissionName()

            };
            index++;
        }
    }


    static class EditTableCellCallback implements IEditTableCellCallback<TableHeader> {
        @Override
        public boolean exec(List<TableHeader> headers, Object[][] columns, int rowIndex, int cellIndex) {
            boolean editState = (Boolean) columns[rowIndex][2];
            if (!editState) {
                return false;
            }
            return headers.get(cellIndex).isEditState();
        }
    }

    public static class MethodParamTable {
        private final String cellName;
        private final boolean genState = true;
        private final String methodName;
        private final String requestName;
        private final String allRequestName;
        private final String permissionName;

        public MethodParamTable(String cellName, String methodName, String requestName, String allRequestName, String permissionName) {
            this.cellName = cellName;
            this.methodName = methodName;
            this.requestName = requestName;
            this.allRequestName = allRequestName;
            this.permissionName = permissionName;
        }

        public String getCellName() {
            return cellName;
        }

        public String getMethodName() {
            return methodName;
        }

        public String getPermissionName() {
            return permissionName;
        }

        public String getRequestName() {
            return requestName;
        }

        public boolean isGenState() {
            return genState;
        }

        public String getAllRequestName() {
            return allRequestName;
        }
    }

    static class TableHeader {
        private final String headerName;
        private final boolean editState;
        private final IEditTableCellCallback callback;

        public TableHeader(String headerName, boolean editState, IEditTableCellCallback callback) {
            this.headerName = headerName;
            this.editState = editState;
            this.callback = callback;
        }

        public String getHeaderName() {
            return headerName;
        }

        public boolean isEditState() {
            return editState;
        }

        public IEditTableCellCallback getCallback() {
            return callback;
        }
    }


    @Override
    public int getRowCount() {
        return columns.length;
    }

    @Override
    public int getColumnCount() {
        return TABLE_HEADERS.size();
    }

    @Override
    public String getColumnName(int columnIndex) {
        return TABLE_HEADERS.get(columnIndex).getHeaderName();
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        Object val = getValueAt(0, columnIndex);
        return val == null ? Object.class : val.getClass();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return TABLE_HEADERS.get(columnIndex).getCallback().exec(TABLE_HEADERS, columns, rowIndex, columnIndex);
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        if (rowIndex < getRowCount() && columnIndex < getColumnCount()) {
            return columns[rowIndex][columnIndex];
        }
        return null;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        columns[rowIndex][columnIndex] = aValue;
        fireTableCellUpdated(rowIndex, columnIndex);
    }

}
